convert scrapbox to html
他のscriptにも流用できるかも知れないtakker.icon
code:script.js
import {ScrapboxParser} from '/api/code/takker/scrapbox-parser.min.js/parser.js';
export function convertSb2HTML({project,title,text} = {}) {
const blocks = ScrapboxParser.parse(text, {hasTitle: title});
return blocks.map(block => {
switch (block.type) {
case 'title':
return convertTitle(title);
case 'codeBlock':
return convertCodeBlock(project, title, block);
case 'table':
return convertTable(project, title, block);
case 'line':
return convertLine(project, block);
}
}).join('\n');
}
function blockBase(block) {
return <div class="line">${block}</div>;
}
function convertTitle(title) {
return <div class="line line-title">${title.text}</div>
}
function convertCodeBlock(project, title, codeBlock) {
const path = https://scrapbox.io/api/code/${project}/${title}/${codeBlock.fileName};
const head = codeBlock.fileName.includes('.') ?
<a href="${codeBlock.fileName}">${codeBlock.fileName}</a>
: codeBlock.fileName;
return blockBase(`<code class="code-block">
<span class="code-block-start" title="${codeBlock.fileName}">
${head}
</span>
<div style="marginLeft: '1.5em'">${codeBlock.content}</div>
</code>`);
}
function convertTable(project, title, table) {
const path = https://scrapbox.io/api/table/${project}/${title}/${table.fileName}.csv;
const td = columns => `
<td class="cell">
${columns.map(node => convertNode(project,node))}
</td>`;
const tr = rows => `
<tr>
${rows.map(columns => td(columns))}
</tr>`;
return blockBase(`
<div class="table-block">
<span class="table-block-start">
<a href=${path}>${table.fileName}</a>
</span>
<table>
${table.cells.map(rows => tr(rows))}
</table>
</div>`);
}
function convertLine(project,line) {
return blockBase(!line.nodes.length ? '<br />' :
line.nodes.map(node => convertNode(project,node)).join(''));
}
function convertNode(project,node) {
switch (node.type) {
case 'quote':
return `
<blockquote class="quote">
<span class="tag">></span>
${node.nodes.map(node => convertNode(project,node))}
</blockquote>`;
case 'helpfeel':
return `
<code class="helpfeel">
<span class="prefix">?</span>
<span> </span>
<span class="entry">node.text</span>
</code>`;
case 'strongImage':
return `
<a href={node.src} rel="noopener noreferrer" target="_blank">
<img src={node.src} class="strong-image" />
</a>`;
case 'strongIcon':
return convertIcon(project, node, {isStrong: true});
case 'strong':
return `
<strong>
${node.nodes.map(node => convertNode(project,node))}
</strong>`;
case 'formula':
return <span class="formula">${node.formula}</span>;
case 'decoration':
return `
<span class="deco">
<span class="{node.decos.map(deco => 'deco-'+deco).join(' ')">
${node.nodes.map(node => convertNode(project,node))}
</span>
</span>`;
case 'code':
return `
<code class="code">
<span class="backquote"> </span>
<span>${node.text}</span>
<span class="backquote"> </span>
</code>`;
case 'commandLine':
return `
<code class="cli">
<span class="prefix">${node.symbol}</span>
<span> </span>
<span class="command">${node.text}</span>
</code>`;
case 'blank':
return <span class="blank">${node.text}</span>
case 'link':
return convertLink(project, node);
case 'image':
return `
<a href=${node.link || node.src}
class="${node.link ? 'link' : null}"
rel="noopener noreferrer"
target="_blank">
<img src="${node.src}" class="image" />
</a>`;
case 'googleMap':
return `
<a
href=${node.url}
rel="noopener noreferrer"
target="_blank"
class="link"
${node.place}
</a>`;
case 'icon':
return convertIcon(project, node);
case 'hashTag':
return `
<a type="hashTag" class="page-link" href="/${project}/${node.href}">
</a>`;
case 'plain':
return node.text;
}
}
function convertIcon(project, icon, {isStrong = false} ={}) {
const path =
icon.pathType === 'relative' ? /${project}/${icon.path} : icon.path;
const name = path.split('/')2; return `
<a class="link icon" href="${path}">
<img
src="/api/pages${path}/icon"
alt="${name}"
title="${name}"
class="icon${isStrong? ' strong-icon' : ''}"
/>
</a>`;
}
function convertLink(project, link) {
switch (link.pathType) {
case 'root':
case 'relative':
const href =
link.pathType === 'relative' ? /${project}/${link.href} : link.href
return <a class="page-link" href="${href}">${link.href}</a>;
case 'absolute':
return `
<a href={link.href} rel="noopener noreferrer" target="_blank">
${link.content || link.href}
</a>`;
}
}
test code
code:js
fetch('/api/pages/hub/議論のためのplatform/text')
.then(res => res.text())
.then(text => convertSb2HTML({project:'hub', title:'議論のためのplatform', text:text,hasTitle:true}))
.then(html=>{
console.log(html);
window.open().document.write(html);
});